/*
 *  Copyright (c) 2009, Hugo Augusto Alves
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of the Hugo Augusto Alves nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.wiscriptor.core;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import org.liteml.parser.LiteParser;
import org.liteml.parser.LiteUtils.Target;
import org.wiscriptor.wiki.Page;
import org.wiscriptor.db.WikiDataBase;
import org.wiscriptor.internalization.I18N;
import org.wiscriptor.utils.Utils;
import org.wiscriptor.gui.MainWindow;
import org.wiscriptor.gui.SettingsDialog;
import org.wiscriptor.io.FileLoader;
import org.wiscriptor.lmldocument.OldLmlDocument;
import org.wiscriptor.utils.Utils.Status;
import org.wiscriptor.wiki.Wiki;

/**
 *
 * @author Hugo
 */
public class WiscriptorController {

    public enum editAction {

        cut, copy, paste, insert, delete
    }
    private static WiscriptorController wiscontroller;
    private Wiki currentWiki = null;
    private WikiDataBase currentWikiDb = null;
    private MainWindow mainWindow;
    private SettingsDialog settingsDialog;
    private LiteParser liteParser = new LiteParser();
    private Page currentPage = new Page();

    public WiscriptorController() {

        I18N.getInstance().getAvailableLanguages();
        // tenta pt-PT, mas como nao tem pega pt-BR
        //I18N.getInstance().load("pt", "PT");
        I18N.getInstance().load("en", "US");
        ////\ teste

        /**/
        // View
        wiscontroller = this;
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                try {
                    JFrame.setDefaultLookAndFeelDecorated(true);
                    JDialog.setDefaultLookAndFeelDecorated(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                mainWindow = new MainWindow(wiscontroller);
                mainWindow.setVisible(true);
            }
        });

//        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
//
//            public boolean dispatchKeyEvent(KeyEvent e) {
//                if (e.isAltDown() && e.isControlDown()) {
//                    //TODO: toogle em menubar
////                    mainWindow.toogleToolBar();
//                    return true;
//                }
//                return false;
//            }
//        });
        /**/
    }

    /*** [[[ called by view ***/
    /**
     * Called by view when change <code>plain</code> to <code>html</code>
     * @param id model id
     * @param text new text
     * @return text formatted in html
     */
    public String editPage(String text) {
        currentPage.setText(text);
        liteParser.setInput(text);
        String res = liteParser.parse(Target.HTML);
        return res;
    }

    /**
     * Make the specified changes in file text
     * @param text current text of file
     * @param newText text to be inserted (only in insertOrUpdate action)
     * @param start start of action
     * @param end end of action
     * @param e action
     * @return text of file after changes
     */
    public String editText(String text, String newText, int start, int end, editAction e) {
        /*
        docModel.setText(text);
        switch (e) {
        case cut:
        docModel.cut(start, end);
        break;
        case copy:
        docModel.copy(start, end);
        break;
        case paste:
        docModel.paste(start, end);
        break;
        case insert:
        docModel.insert(start, end, newText);
        break;
        case delete:
        docModel.del(start, end);
        break;
        }
        return docModel.getText();
         */
        return "Not implemented yet";
    }

    /** TODO: remover referencia a classe antiga */
    public String formatText(String text, OldLmlDocument.marks m, int start, int end) {

        //return docModel.format(text, m, start, end);
        return "Not implemented yet";
    }

    public Page getPage() {
        if (currentPage == null) {
            return null;
        }
        return new Page(currentPage);
    }

    public void createPage() {
        currentPage = new Page();
    }

    public Utils.Status openPage(String name) {
        if (currentWiki == null || !currentWiki.isCreated()) {
            return Status.NOT_WIKI;
        }
        Page p = currentWikiDb.getPage(name);
        if (p == null) {
            return Status.NOT_PAGE;
        }
        currentPage = p;
        // TODO: buscar na tabela e preencher tags
        return Utils.Status.SUCCESS;
    }

    public Utils.Status savePage(String name, String text, String category, String tags) {
        boolean changed = false;

        if (currentWiki == null || !currentWiki.isCreated()) {
            return Status.NOT_WIKI;
        }
        if (name == null || text == null || category == null || tags == null || name.equals("")) {
            return Utils.Status.ERROR;
        }

        if (currentPage == null) {
            currentPage = new Page();
        }

        if (!currentPage.getName().equals(name)) {
            changed = true;
            currentPage = new Page();
            currentPage.setName(name);
        }

        if (!currentPage.getName().equals(text)) {
            changed = true;
            currentPage.setText(text);
        }

        if (!currentPage.getName().equals(category)) {
            changed = true;
            currentPage.setCategory(category);
        }


        // TODO: verificar tags!!!

        if (changed) {
            currentPage.getVersion().increaseMinor(); // incrementa versão
            // TODO: gerar um comentario baseado nas mudancas sofridas
            currentPage.setComment(new Date().toString());
            System.err.println(currentPage.getVersion().getVersionString());
            currentWikiDb.insertOrUpdate(currentPage);
            Status res = currentWiki.savePage(currentPage);
            return res;
        } else {
            return Status.NOT_NEEDED;
        }

    }

    public String getPageContent() {
        liteParser.setInput(currentPage.getText());
        return liteParser.parse(Target.HTML);
    }

    public String getPageRawText() {
        return currentPage.getText();
    }

    public Utils.Status createWiki(String wikiName) {
        currentWiki = new Wiki(wikiName);
        currentWikiDb = new WikiDataBase(currentWiki.getDbName());
        if (currentWiki.isCreated()) {
            return Utils.Status.SUCCESS;
        } else {
            return Utils.Status.ERROR;
        }
    }

    public Utils.Status openWiki(String wikiName) {
        // TODO: verificar se existe a wiki para abrir
        return createWiki(wikiName);
    }

    public String getCurrentWikiName() {
        if (currentWiki == null) {
            return "";
        } else {
            return currentWiki.getName();
        }
    }

    public String[] getWikis() {
        // TODO: provisorio - pegar do arquivo sqlite
        try {
            File wikisDir = FileLoader.getInstance().loadFile("wikis");
            return wikisDir.list();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    
    public ArrayList<String> getCategoriesPages(String cat) {
        ArrayList<String> tmp = new ArrayList<String>();
        tmp = currentWikiDb.getCategoriesWithParent(cat);
        ArrayList<String> list = new ArrayList<String>(tmp);
        tmp = currentWikiDb.getPagesWithCategory(cat);
        for(String s : tmp) {
            list.add(s);
        }
        return list;
    }

    public ArrayList<String> getCategories() {
        return currentWikiDb.getCategories();
    }

    public String getCategory(String page) {
        return currentWikiDb.getCategoryOfPage(page);
    }

    public void setLAF(String s) {
        if (s != null && !s.equals("")) {
            mainWindow.setLAF(s);
            // TODO: colocar em thread?? aqui e em changeLanguage
            try {
                Settings.getInstance().setLookAndFeel(s);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(null, I18N.getInstance().getValueForKey(I18N.key.settingserrorMessage),
                        I18N.getInstance().getValueForKey(I18N.key.settingserrorTitle), JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    public void showSettingsDialog() {
        if (settingsDialog == null) {
            settingsDialog = new SettingsDialog(null, true, this);
        }
        settingsDialog.setVisible(true);
    }

    public void changeLanguage(String language, String country) {
        if (language != null && country != null && !language.equals("") && !country.equals("")) {
            I18N.getInstance().load(language, country);
            settingsDialog.reloadLabels();
            mainWindow.reloadLabels();
            try {
                Settings.getInstance().setCountry(country);
                Settings.getInstance().setLanguage(language);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(null, I18N.getInstance().getValueForKey(I18N.key.settingserrorMessage),
                        I18N.getInstance().getValueForKey(I18N.key.settingserrorTitle), JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    public static void main(String[] args) {
        new WiscriptorController();
    }
}
